home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
graphic
/
frasr182.zip
/
ZOOM.C
< prev
Wrap
C/C++ Source or Header
|
1993-01-05
|
19KB
|
540 lines
/*
zoom.c - routines for zoombox manipulation and for panning
*/
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fractint.h"
#include "prototyp.h"
/* screen dimensions here are (1.0,1.0) corresponding to (xdots-1,ydots-1) */
extern double zbx,zby; /* topleft of unrotated zoombox */
extern double zwidth,zdepth,zskew; /* zoombox size & shape */
extern int zrotate; /* * 2.5 degree increments */
extern int boxcount,boxx[],boxy[]; /* co-ords of each zoombox pixel */
extern int xdots,ydots,sxdots,sydots,sxoffs,syoffs;
extern double dxsize,dysize; /* xdots-1, ydots-1 */
extern double xxmin,yymin,xxmax,yymax,xx3rd,yy3rd;
extern double sxmin,symin,sxmax,symax,sx3rd,sy3rd;
/* top left corner of screen is (xxmin,yymax) */
/* bottom left corner of screen is (xx3rd,yy3rd) */
/* bottom right corner of screen is (xxmax,yymin) */
extern double plotmx1,plotmx2,plotmy1,plotmy2;
extern int calc_status; /* status of calculations */
extern int fractype; /* fractal type */
extern char stdcalcmode; /* '1', '2', 'g', 'b', or 't' */
extern int num_worklist; /* resume worklist for standard engine */
extern struct workliststuff worklist[MAXCALCWORK];
extern char dstack[4096]; /* common temp, used for get_line/put_line */
extern int potflag;
extern int pot16bit;
extern float finalaspectratio;
extern float screenaspect;
struct coords {
int x,y;
};
#define PIXELROUND 0.00001
static void _fastcall drawlines(struct coords, struct coords, int, int);
static void _fastcall addbox(struct coords);
static void _fastcall zmo_calc(double, double, double *, double *);
static int check_pan();
static void fix_worklist();
static void _fastcall move_row(int fromrow,int torow,int col);
void drawbox(int drawit)
{ struct coords tl,bl,tr,br; /* dot addr of topleft, botleft, etc */
double tmpx,tmpy,dx,dy,rotcos,rotsin,ftemp1,ftemp2;
double fxwidth,fxskew,fydepth,fyskew,fxadj;
if (zwidth==0) { /* no box to draw */
if (boxcount!=0) { /* remove the old box from display */
clearbox(); /* asm routine */
boxcount = 0; }
reset_zoom_corners();
return; }
ftemp1 = PI*zrotate/72; /* convert to radians */
rotcos = cos(ftemp1); /* sin & cos of rotation */
rotsin = sin(ftemp1);
/* do some calcs just once here to reduce fp work a bit */
fxwidth = sxmax-sx3rd;
fxskew = sx3rd-sxmin;
fydepth = sy3rd-symax;
fyskew = symin-sy3rd;
fxadj = zwidth*zskew;
/* calc co-ords of topleft & botright corners of box */
tmpx = zwidth/-2+fxadj; /* from zoombox center as origin, on xdots scale */
tmpy = zdepth*finalaspectratio/2;
dx = (rotcos*tmpx - rotsin*tmpy) - tmpx; /* delta x to rotate topleft */
dy = tmpy - (rotsin*tmpx + rotcos*tmpy); /* delta y to rotate topleft */
/* calc co-ords of topleft */
ftemp1 = zbx + dx + fxadj;
ftemp2 = zby + dy/finalaspectratio;
tl.x = ftemp1*(dxsize+PIXELROUND); /* screen co-ords */
tl.y = ftemp2*(dysize+PIXELROUND);
xxmin = sxmin + ftemp1*fxwidth + ftemp2*fxskew; /* real co-ords */
yymax = symax + ftemp2*fydepth + ftemp1*fyskew;
/* calc co-ords of bottom right */
ftemp1 = zbx + zwidth - dx - fxadj;
ftemp2 = zby - dy/finalaspectratio + zdepth;
br.x = ftemp1*(dxsize+PIXELROUND);
br.y = ftemp2*(dysize+PIXELROUND);
xxmax = sxmin + ftemp1*fxwidth + ftemp2*fxskew;
yymin = symax + ftemp2*fydepth + ftemp1*fyskew;
/* do the same for botleft & topright */
tmpx = zwidth/-2 - fxadj;
tmpy = 0.0-tmpy;
dx = (rotcos*tmpx - rotsin*tmpy) - tmpx;
dy = tmpy - (rotsin*tmpx + rotcos*tmpy);
ftemp1 = zbx + dx - fxadj;
ftemp2 = zby + dy/finalaspectratio + zdepth;
bl.x = ftemp1*(dxsize+PIXELROUND);
bl.y = ftemp2*(dysize+PIXELROUND);
xx3rd = sxmin + ftemp1*fxwidth + ftemp2*fxskew;
yy3rd = symax + ftemp2*fydepth + ftemp1*fyskew;
ftemp1 = zbx + zwidth - dx + fxadj;
ftemp2 = zby - dy/finalaspectratio;
tr.x = ftemp1*(dxsize+PIXELROUND);
tr.y = ftemp2*(dysize+PIXELROUND);
if (boxcount!=0) { /* remove the old box from display */
clearbox(); /* asm routine */
boxcount = 0; }
if (drawit) { /* caller wants box drawn as well as co-ords calc'd */
#ifndef XFRACT
/* build the list of zoom box pixels */
addbox(tl); addbox(tr); /* corner pixels */
addbox(bl); addbox(br);
drawlines(tl,tr,bl.x-tl.x,bl.y-tl.y); /* top & bottom lines */
drawlines(tl,bl,tr.x-tl.x,tr.y-tl.y); /* left & right lines */
#else
boxx[0] = tl.x + sxoffs;
boxy[0] = tl.y + syoffs;
boxx[1] = tr.x + sxoffs;
boxy[1] = tr.y + syoffs;
boxx[2] = br.x + sxoffs;
boxy[2] = br.y + syoffs;
boxx[3] = bl.x + sxoffs;
boxy[3] = bl.y + syoffs;
boxcount = 1;
#endif
dispbox(); /* asm routine to paint it */
}
}
static void _fastcall drawlines(struct coords fr, struct coords to,
int dx, int dy)
{ int xincr,yincr,ctr;
int altctr,altdec,altinc;
struct coords tmpp,line1,line2;
if (abs(to.x-fr.x) > abs(to.y-fr.y)) { /* delta.x > delta.y */
if (fr.x>to.x) { /* swap so from.x is < to.x */
tmpp = fr; fr = to; to = tmpp; }
xincr = (to.x-fr.x)*4/sxdots+1; /* do every 1st, 2nd, 3rd, or 4th dot */
ctr = (to.x-fr.x-1)/xincr;
altdec = abs(to.y-fr.y)*xincr;
altinc = to.x-fr.x;
altctr = altinc/2;
yincr = (to.y>fr.y)?1:-1;
line2.x = (line1.x = fr.x) + dx;
line2.y = (line1.y = fr.y) + dy;
while (--ctr>=0) {
line1.x += xincr;
line2.x += xincr;
altctr -= altdec;
while (altctr<0) {
altctr += altinc;
line1.y += yincr;
line2.y += yincr;
}
addbox(line1);
addbox(line2);
}
}
else { /* delta.y > delta.x */
if (fr.y>to.y) { /* swap so from.y is < to.y */
tmpp = fr; fr = to; to = tmpp; }
yincr = (to.y-fr.y)*4/sydots+1; /* do every 1st, 2nd, 3rd, or 4th dot */
ctr = (to.y-fr.y-1)/yincr;
altdec = abs(to.x-fr.x)*yincr;
altinc = to.y-fr.y;
altctr = altinc/2;
xincr = (to.x>fr.x) ? 1 : -1;
line2.x = (line1.x = fr.x) + dx;
line2.y = (line1.y = fr.y) + dy;
while (--ctr>=0) {
line1.y += yincr;
line2.y += yincr;
altctr -= altdec;
while (altctr<0) {
altctr += altinc;
line1.x += xincr;
line2.x += xincr;
}
addbox(line1);
addbox(line2);
}
}
}
static void _fastcall addbox(struct coords point)
{
point.x += sxoffs;
point.y += syoffs;
if (point.x >= 0 && point.x < sxdots && point.y >= 0 && point.y < sydots) {
boxx[boxcount] = point.x;
boxy[boxcount] = point.y;
++boxcount;
}
}
void moveboxf(double dx, double dy)
{ int align,row,col;
align = check_pan();
if (dx!=0.0) {
if ((zbx += dx) + zwidth/2 < 0) /* center must stay onscreen */
zbx = zwidth/-2;
if (zbx + zwidth/2 > 1)
zbx = 1.0 - zwidth/2;
if (align != 0
&& ((col = zbx*(dxsize+PIXELROUND)) & (align-1)) != 0) {
if (dx > 0) col += align;
col -= col & (align-1); /* adjust col to pass alignment */
zbx = (double)col/dxsize; }
}
if (dy!=0.0) {
if ((zby += dy) + zdepth/2 < 0)
zby = zdepth/-2;
if (zby + zdepth/2 > 1)
zby = 1.0 - zdepth/2;
if (align != 0
&& ((row = zby*(dysize+PIXELROUND)) & (align-1)) != 0) {
if (dy > 0) row += align;
row -= row & (align-1);
zby = (double)row/dysize; }
}
}
static void _fastcall chgboxf(double dwidth, double ddepth)
{
if (zwidth+dwidth > 1)
dwidth = 1.0-zwidth;
if (zwidth+dwidth < 0.05)
dwidth = 0.05-zwidth;
zwidth += dwidth;
if (zdepth+ddepth > 1)
ddepth = 1.0-zdepth;
if (zdepth+ddepth < 0.05)
ddepth = 0.05-zdepth;
zdepth += ddepth;
moveboxf(dwidth/-2,ddepth/-2); /* keep it centered & check limits */
}
void resizebox(int steps)
{
double deltax,deltay;
if (zdepth*screenaspect > zwidth) { /* box larger on y axis */
deltay = steps * 0.036 / screenaspect;
delt